package windbell.domain.risk.impl;

import com.google.common.base.Objects;
import edu.fudan.langlab.domain.document.IDocument;
import edu.fudan.langlab.domain.statemachine.ModelObjectLogService;
import edu.fudan.mylang.pf.BaseModelObject;
import edu.fudan.mylang.pf.IObjectFactory;
import edu.fudan.mylang.utils.DateUtil;
import java.util.Collection;
import java.util.Date;
import javax.persistence.CascadeType;
import javax.persistence.Column;
import javax.persistence.DiscriminatorColumn;
import javax.persistence.DiscriminatorValue;
import javax.persistence.Entity;
import javax.persistence.JoinColumn;
import javax.persistence.ManyToOne;
import javax.persistence.OneToMany;
import javax.persistence.Table;
import org.eclipse.xtext.xbase.lib.Functions.Function1;
import org.eclipse.xtext.xbase.lib.IterableExtensions;
import org.eclipse.xtext.xbase.lib.ObjectExtensions;
import org.eclipse.xtext.xbase.lib.Procedures.Procedure1;
import org.hibernate.annotations.DiscriminatorOptions;
import windbell.domain.risk.RiskCause;
import windbell.domain.risk.RiskCheckItem;
import windbell.domain.risk.RiskFixType;
import windbell.domain.risk.RiskLevel;
import windbell.domain.risk.RiskReport;
import windbell.domain.risk.RiskReportDerived;
import windbell.domain.risk.RiskReportQrCode;
import windbell.domain.risk.RiskReportStatus;
import windbell.domain.risk.RiskType;
import windbell.domain.risk.impl.RiskCauseImpl;
import windbell.domain.risk.impl.RiskCheckItemImpl;
import windbell.domain.risk.impl.RiskFixTypeImpl;
import windbell.domain.risk.impl.RiskLevelImpl;
import windbell.domain.risk.impl.RiskReportDerivedImpl;
import windbell.domain.risk.impl.RiskReportQrCodeImpl;
import windbell.domain.risk.impl.RiskTypeImpl;
import windbell.domain.risk.proxy.RiskReportProxy;

@Entity
@DiscriminatorValue("RISKREPORT_TYPE")
@DiscriminatorOptions(force = true)
@DiscriminatorColumn(length = 64)
@Table(name = "riskreport")
public class RiskReportImpl extends BaseModelObject implements RiskReport {
  public RiskReportImpl() {
    super();
  }
  
  public RiskReportImpl(final RiskCheckItem riskCheckItem) {
    super();
    this.riskCheckItem = riskCheckItem;
  }
  
  private RiskReportStatus Status;
  
  public RiskReportStatus getStatus() {
    return this.Status;
  }
  
  private ModelObjectLogService getModelObjectLogService() {
    return getBeanFactory().getBean(ModelObjectLogService.class);
  }
  
  private void _start() {
    
    RiskReportDerived riskReportDerived=RiskReportDerivedImpl.create(getObjectFactory());
    
    this.derived = riskReportDerived;
    this.derived.updateDerived(this);
    Status=RiskReportStatus.created;
  }
  
  public void start() {
    if(Status==null){
    	_start();
    	getModelObjectLogService().createLog(this,"Status","Start");
    	getBeanFactory().getBean(windbell.domain.risk.events.RiskReportEventsManager.class).fireStarted(this);					
    }else{
    	throw new edu.fudan.langlab.domain.statemachine.InvalidStateException("allready started");
    }
  }
  
  private void _update(final Procedure1<? super RiskReport> updater) {
    
    updater.apply(this);
  }
  
  public void update(final Procedure1<? super RiskReport> updater) {
    if(Status==RiskReportStatus.created){
    	_update(updater);
    	getModelObjectLogService().createLog(this,"Status","update");
    	getBeanFactory().getBean(windbell.domain.risk.events.RiskReportEventsManager.class).fireUpdate(this,updater);						
    }else{
    	throw new edu.fudan.langlab.domain.statemachine.InvalidStateException(Status.name());
    }
  }
  
  private IDocument _createDocument(final Procedure1<? super IDocument> init) {
    RiskReportQrCode _xblockexpression = null;
    {
      boolean _and = false;
      boolean _notEquals = (!Objects.equal(this.documents, null));
      if (!_notEquals) {
        _and = false;
      } else {
        int _size = this.documents.size();
        boolean _greaterThan = (_size > 0);
        _and = (_notEquals && _greaterThan);
      }
      if (_and) {
        final Function1<RiskReportQrCode,Boolean> _function = new Function1<RiskReportQrCode,Boolean>() {
            public Boolean apply(final RiskReportQrCode it) {
              return Boolean.valueOf(true);
            }
          };
        RiskReportQrCode _findFirst = IterableExtensions.<RiskReportQrCode>findFirst(this.documents, _function);
        this.removeDocument(_findFirst);
      }
      RiskReportQrCode _createAndAddtoDocuments = this.createAndAddtoDocuments();
      final Procedure1<RiskReportQrCode> _function_1 = new Procedure1<RiskReportQrCode>() {
          public void apply(final RiskReportQrCode it) {
            init.apply(it);
          }
        };
      RiskReportQrCode _doubleArrow = ObjectExtensions.<RiskReportQrCode>operator_doubleArrow(_createAndAddtoDocuments, _function_1);
      _xblockexpression = (_doubleArrow);
    }
    return _xblockexpression;
  }
  
  public IDocument createDocument(final Procedure1<? super IDocument> init) {
    if(Status==RiskReportStatus.created){
    	IDocument result = _createDocument(init);
    	getModelObjectLogService().createLog(this,"Status","createDocument");
    	getBeanFactory().getBean(windbell.domain.risk.events.RiskReportEventsManager.class).fireCreateDocument(this,init);
    	return result;
    }else{
    	throw new edu.fudan.langlab.domain.statemachine.InvalidStateException("Status.name()");
    }
  }
  
  private void _removeDocument(final IDocument document) {
    this.removeFromDocuments(((RiskReportQrCode) document));
  }
  
  public void removeDocument(final IDocument document) {
    if(Status==RiskReportStatus.created){
    	_removeDocument(document);
    	getModelObjectLogService().createLog(this,"Status","removeDocument");
    	getBeanFactory().getBean(windbell.domain.risk.events.RiskReportEventsManager.class).fireRemoveDocument(this,document);						
    }else{
    	throw new edu.fudan.langlab.domain.statemachine.InvalidStateException(Status.name());
    }
  }
  
  private void _finish() {
    
    Status=RiskReportStatus.finished;
    Date _day = DateUtil.today();
    this.finishDate = _day;
  }
  
  public void finish() {
    if(Status==RiskReportStatus.created){
    	_finish();
    	getModelObjectLogService().createLog(this,"Status","finish");
    	getBeanFactory().getBean(windbell.domain.risk.events.RiskReportEventsManager.class).fireFinish(this);						
    }else{
    	throw new edu.fudan.langlab.domain.statemachine.InvalidStateException(Status.name());
    }
  }
  
  private void _reopen() {
    
    Status=RiskReportStatus.created;
  }
  
  public void reopen() {
    if(Status==RiskReportStatus.finished){
    	_reopen();
    	getModelObjectLogService().createLog(this,"Status","reopen");
    	getBeanFactory().getBean(windbell.domain.risk.events.RiskReportEventsManager.class).fireReopen(this);						
    }else{
    	throw new edu.fudan.langlab.domain.statemachine.InvalidStateException(Status.name());
    }
  }
  
  public Boolean isCreated() {
    return windbell.domain.risk.RiskReportStatus.created==Status;
  }
  
  public Boolean isFinished() {
    return windbell.domain.risk.RiskReportStatus.finished==Status;
  }
  
  @JoinColumn(name = "riskCheckItem_id")
  @ManyToOne(targetEntity = RiskCheckItemImpl.class, cascade = { CascadeType.MERGE, CascadeType.PERSIST })
  private RiskCheckItem riskCheckItem;
  
  public RiskCheckItem getRiskCheckItem() {
    return this.riskCheckItem;
  }
  
  private Date foundDate;
  
  public Date getFoundDate() {
    return this.foundDate;
  }
  
  public RiskReport setFoundDate(final Date foundDate) {
    this.foundDate = foundDate;
    return this;			
    
  }
  
  @Column(length = 2048)
  private String reason;
  
  public String getReason() {
    return this.reason;
  }
  
  public RiskReport setReason(final String reason) {
    this.reason = reason;
    return this;			
    
  }
  
  @Column(length = 2048)
  private String analysis;
  
  public String getAnalysis() {
    return this.analysis;
  }
  
  public RiskReport setAnalysis(final String analysis) {
    this.analysis = analysis;
    return this;			
    
  }
  
  @Column(length = 2048)
  private String solution;
  
  public String getSolution() {
    return this.solution;
  }
  
  public RiskReport setSolution(final String solution) {
    this.solution = solution;
    return this;			
    
  }
  
  private String location;
  
  public String getLocation() {
    return this.location;
  }
  
  public RiskReport setLocation(final String location) {
    this.location = location;
    return this;			
    
  }
  
  @JoinColumn(name = "riskType_id")
  @ManyToOne(targetEntity = RiskTypeImpl.class, cascade = { CascadeType.MERGE, CascadeType.PERSIST })
  private RiskType riskType;
  
  public RiskType getRiskType() {
    return this.riskType;
  }
  
  public RiskReport setRiskType(final RiskType riskType) {
    this.riskType = riskType;
    return this;			
    
  }
  
  private Double cost;
  
  public Double getCost() {
    return this.cost;
  }
  
  public RiskReport setCost(final Double cost) {
    this.cost = cost;
    return this;			
    
  }
  
  private String taskOwner;
  
  public String getTaskOwner() {
    return this.taskOwner;
  }
  
  public RiskReport setTaskOwner(final String taskOwner) {
    this.taskOwner = taskOwner;
    return this;			
    
  }
  
  private String reviewOwner;
  
  public String getReviewOwner() {
    return this.reviewOwner;
  }
  
  public RiskReport setReviewOwner(final String reviewOwner) {
    this.reviewOwner = reviewOwner;
    return this;			
    
  }
  
  private Date dueDate;
  
  public Date getDueDate() {
    return this.dueDate;
  }
  
  public RiskReport setDueDate(final Date dueDate) {
    this.dueDate = dueDate;
    return this;			
    
  }
  
  private Date finishDate;
  
  public Date getFinishDate() {
    return this.finishDate;
  }
  
  public RiskReport setFinishDate(final Date finishDate) {
    this.finishDate = finishDate;
    return this;			
    
  }
  
  private String description;
  
  public String getDescription() {
    return this.description;
  }
  
  public RiskReport setDescription(final String description) {
    this.description = description;
    return this;			
    
  }
  
  @JoinColumn(name = "riskLevel_id")
  @ManyToOne(targetEntity = RiskLevelImpl.class, cascade = { CascadeType.MERGE, CascadeType.PERSIST })
  private RiskLevel riskLevel;
  
  public RiskLevel getRiskLevel() {
    return this.riskLevel;
  }
  
  public RiskReport setRiskLevel(final RiskLevel riskLevel) {
    this.riskLevel = riskLevel;
    return this;			
    
  }
  
  private String checker;
  
  public String getChecker() {
    return this.checker;
  }
  
  public RiskReport setChecker(final String checker) {
    this.checker = checker;
    return this;			
    
  }
  
  @JoinColumn(name = "riskCause_id")
  @ManyToOne(targetEntity = RiskCauseImpl.class, cascade = { CascadeType.MERGE, CascadeType.PERSIST })
  private RiskCause riskCause;
  
  public RiskCause getRiskCause() {
    return this.riskCause;
  }
  
  public RiskReport setRiskCause(final RiskCause riskCause) {
    this.riskCause = riskCause;
    return this;			
    
  }
  
  private String reporter;
  
  public String getReporter() {
    return this.reporter;
  }
  
  public RiskReport setReporter(final String reporter) {
    this.reporter = reporter;
    return this;			
    
  }
  
  @JoinColumn(name = "riskFixType_id")
  @ManyToOne(targetEntity = RiskFixTypeImpl.class, cascade = { CascadeType.MERGE, CascadeType.PERSIST })
  private RiskFixType riskFixType;
  
  public RiskFixType getRiskFixType() {
    return this.riskFixType;
  }
  
  public RiskReport setRiskFixType(final RiskFixType riskFixType) {
    this.riskFixType = riskFixType;
    return this;			
    
  }
  
  @JoinColumn(name = "derived_id")
  @ManyToOne(targetEntity = RiskReportDerivedImpl.class, cascade = { CascadeType.MERGE, CascadeType.PERSIST })
  private RiskReportDerived derived;
  
  public RiskReportDerived getDerived() {
    return this.derived;
  }
  
  public RiskReport setDerived(final RiskReportDerived derived) {
    this.derived = derived;
    return this;			
    
  }
  
  @OneToMany(targetEntity = RiskReportQrCodeImpl.class, cascade = { CascadeType.MERGE, CascadeType.PERSIST, CascadeType.REMOVE }, mappedBy = "riskReport")
  private Collection<RiskReportQrCode> documents = new java.util.ArrayList<windbell.domain.risk.RiskReportQrCode>();;
  
  public Collection<RiskReportQrCode> getDocuments() {
    return this.documents;
  }
  
  public RiskReportQrCode createAndAddtoDocuments() {
    getDocuments().size();
    windbell.domain.risk.RiskReportQrCode riskReportQrCode = new windbell.domain.risk.impl.RiskReportQrCodeImpl(this);
    getObjectFactory().create(riskReportQrCode);
    getDocuments().add(riskReportQrCode);
    return riskReportQrCode;
    
  }
  
  public RiskReportQrCode createAndAddtoDocuments(final Procedure1<RiskReportQrCode> updater) {
    getDocuments().size();
    windbell.domain.risk.RiskReportQrCode riskReportQrCode = new windbell.domain.risk.impl.RiskReportQrCodeImpl(this);
    getObjectFactory().create(riskReportQrCode);
    getDocuments().add(riskReportQrCode);
    return riskReportQrCode;
    
  }
  
  public RiskReport removeAllDocuments() {
    for(RiskReportQrCode obj : this.documents){
    	getObjectFactory().delete(obj);
    }
    this.documents.clear();
    return this;	
    
  }
  
  public RiskReport removeFromDocuments(final RiskReportQrCode riskReportQrCode) {
    this.documents.remove(riskReportQrCode);
    getObjectFactory().delete(riskReportQrCode);
    return this;
    
  }
  
  public static RiskReport create(final RiskCheckItem riskCheckItem, final IObjectFactory objectFactory) {
    windbell.domain.risk.RiskReport riskReport = new windbell.domain.risk.impl.RiskReportImpl(
    	riskCheckItem
    );
    objectFactory.create(riskReport);
    riskReport.start();
    return riskReport;			
    
  }
  
  public static RiskReport createRiskReportImpl(final RiskCheckItem riskCheckItem, final IObjectFactory objectFactory, final Procedure1<RiskReport> init) {
    windbell.domain.risk.RiskReport riskReport = new windbell.domain.risk.impl.RiskReportImpl(
    	riskCheckItem
    );
    objectFactory.create(riskReport);
    init.apply(riskReport);
    riskReport.start();
    return riskReport;			
    
  }
  
  public RiskReportProxy toProxy() {
    windbell.domain.risk.proxy.RiskReportProxy proxy = new windbell.domain.risk.proxy.RiskReportProxy();
    proxy.setId(this.getId());
    if(this instanceof edu.fudan.mylang.pf.INamedModelObject){
    	proxy.setName(((edu.fudan.mylang.pf.INamedModelObject)this).getEntityName());
    }
    proxy.setStatus(this.getStatus().name());
    return proxy;
    
  }
}
